use e_utils::AnyResult;
use serde::{Deserialize, Serialize};
use std::ffi::OsString;
use structopt::{clap::arg_enum, StructOpt};

arg_enum! {
    /// Api接口
    #[derive(Deserialize, Serialize, Debug, StructOpt, Clone, PartialEq, Copy)]
    pub enum OptsApi {
        None,
        Active,
        Office,
        Clean,
        Drive,
        Fileinfo,
        DesktopInfo,
        DiskInfo,
    }
}

/// e-app
/// ------------------------------------------------------
#[derive(StructOpt, Debug, Clone, Serialize, Deserialize)]
#[structopt(name = "", setting = structopt::clap::AppSettings::TrailingVarArg,)]
#[structopt(after_help = r#"
# Example
-----------------------------------------------------------
# Cmd Example Active SYSTEM
```sh
e-app.exe --api active --task rkms -- kms.03k.org
e-app.exe --api active --task active -- YVWGF-BXNMC-HTQYQ-CPQ99-66QFC
e-app.exe --api active --task check
```
-----------------------------------------------------------

# Cmd Example deActive SYSTEM
```sh
e-app.exe --api active --task ckms
e-app.exe --api active --task deactive
e-app.exe --api active --task check
```
-----------------------------------------------------------

# Cmd Example empty task
```sh
e-app.exe --api clean --task empty-recycle-bin
e-app.exe --api clean --task empty-access-log
e-app.exe --api clean --task empty-netshare
e-app.exe --api clean --task empty-activity-history
e-app.exe --api clean --task empty-run-history
```
-----------------------------------------------------------

# Cmd Example Drive commands
```sh
# Find drive from node
e-app.exe  --api Drive --full --task findnodes --filter "Intel(R) Ethernet Controller (3) I225-V #4" -- =net
# Print drive info
e-app.exe  --api Drive --full --task print -- =net
# Remove drive
e-app.exe  --api Drive --full --task remove --args /force --filter "Intel(R) Ethernet Controller (3) I225-V #4" -- =net
# Disable drive
e-app.exe  --api Drive --full --task disable --args /force --filter "Intel(R) Ethernet Controller (3) I225-V #4" -- =net
# Enable drive
e-app.exe  --api Drive --full --task enable --args /force --filter "Intel(R) Ethernet Controller (3) I225-V #4" -- =net
# Restart drive
e-app.exe  --api Drive --full --task restart --args /force --filter "Intel(R) Ethernet Controller (3) I225-V #4" -- =net
# Scan all new drive
e-app.exe --api Drive --task scan
# Delete drive throgh node info : /reboot
e-app.exe  --api Drive --full --task delete-find --args /force --filter "Intel(R) Ethernet Controller (3) I225-V #4" -- =net
# Delete with uninstall drive throgh inf file : /reboot
e-app.exe --api Drive --task delete --args F:\device.inf /uninstall /force
# Add drive throgh inf file : /reboot
e-app.exe --api Drive --task add --args F:\device.inf /install /force
# Add more drive throgh inf file : /reboot
e-app.exe --api Drive --task add-file --args F:\drives /install /force
# Output more or one drive <oem#.inf | *> <target directory>
e-app.exe --api Drive --task export --args * F:\drives
```
-----------------------------------------------------------

# Cmd Example Fileinfo commands
```sh
e-app.exe --api Fileinfo --task all --args D:\hg-autotest-history\hg-autotest-v3.0.9\tools\heg-tools\heg-upload-mes.exe
e-app.exe --api Fileinfo --task copy-lib --args E:\Desktop\hg-autotest-v3.0.7\tools\heg-tools\e-app.exe  E:\Desktop\libs
e-app.exe --api Fileinfo --task print --args D:\hg-autotest-history\hg-autotest-v3.0.9\tools\heg-tools\heg-upload-mes.exe
```
-----------------------------------------------------------

# Cmd Example Net commands
```sh
e-app.exe --api Net --task print -- ~has_dhcp_ip ~is_connected ~1000 Ethernet
e-app.exe --api Net --task check-mac -- ~has_dhcp_ip ~is_connected ~1000 Ethernet
e-app.exe --api Net --task interfaces -- Ethernet
e-app.exe --api Net --task interfaces-all
e-app.exe --api Net --task print-all
e-app.exe --api Net --task auto-dhcp -- Ethernet
e-app.exe --api Net --task auto-dhcp -- "以太网 3"
e-app.exe --api Net --task sync-datetime --args time.windows.com
e-app.exe --api Net --task ping --args <源> <目标> <次数/s>
e-app.exe --api Net --task interfaces-ping --args <目标> <次数/s> -- Ethernet
```
-----------------------------------------------------------

# Cmd Example Desktop Info commands
```sh
e-app.exe --api DesktopInfo --task print
e-app.exe --api DesktopInfo --task print --args <属性0则全部> <用户名>
e-app.exe --api DesktopInfo --task all
```
-----------------------------------------------------------
"#)]
#[allow(clippy::struct_excessive_bools)]
pub struct Opts {
  /// API接口
  #[structopt(required = true, short, long, possible_values = &OptsApi::variants(), case_insensitive = true)]
  pub api: OptsApi,
  /// 任务
  #[structopt(long, required = false, default_value = "")]
  pub task: String,
  /// 是否完整信息
  #[structopt(long)]
  pub full: bool,
  /// 筛选排除
  #[structopt(long, required = false)]
  pub filter: Vec<String>,
  /// 扩展参数
  #[structopt(long, required = false)]
  pub args: Vec<String>,
  /// 扩展指令
  #[structopt(required = false, last = true)]
  pub command: Vec<String>,
}
impl Default for Opts {
  fn default() -> Self {
    Self {
      api: OptsApi::None,
      task: String::new(),
      full: false,
      // verbose: 0,
      args: Vec::new(),
      filter: Vec::new(),
      command: Vec::new(),
    }
  }
}

impl Opts {
  /// # Example
  ///```rust
  /// fn main() -> e_utils::AnyResult<()> {
  ///   if e_app::input::Opts::check_empty() {
  ///     let _ = app::MyApp::launch()?;
  ///   } else {
  ///     let opts = e_app::input::Opts::new(None as Option<Vec<String>>)?;
  ///     let res = e_app::input::api(opts)?;
  ///     println!("{}", res.to_str()?);
  ///   }
  ///   Ok(())
  /// }
  /// ```
  pub fn new<I>(args: Option<I>) -> AnyResult<Self>
  where
    Self: Sized,
    I: IntoIterator,
    I::Item: Into<OsString> + Clone,
  {
    match args {
      Some(arg) => match Opts::from_iter_safe(arg) {
        Ok(opt) => Ok(opt),
        Err(e) => Err(e.into()),
      },
      None => Ok(Opts::from_args()),
    }
  }
  /// # 检查空
  pub fn check_empty() -> bool {
    std::env::args().len() == 1
  }
}
